#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "esp_log.h"

#include "gpio.h"
#include "blufi.h"
#include "OTA.h"

const char* TAG_GPIO ="TAG_GIPO";
QueueHandle_t gpio_evt_queue;


void IRAM_ATTR gpio_isr_handler(void* arg) 
{
    //把中断消息插入到队列的后面，将gpio的io参数传递到队列中
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
    
}

void gpio_task(void* arg) 
{
    ESP_LOGI(TAG_GPIO,"GPIO线程启动");
    uint32_t io_num;
    for(;;)
    {
        //不断读取gpio队列，读取完后将删除队列
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY))
        {
            vTaskDelay(100/portTICK_PERIOD_MS);
            if(!(gpio_get_level(io_num)==0)){continue;}
            switch (io_num)
            {
            case GPIO_NUM_0:
                ESP_LOGW("ESP_OTA","开始OTA升级");
                esp_start_ota();
                break;
            case GPIO_NUM_2:
                if(!(cur_blec_inf.blufi_is_init)){
                    ESP_LOGW(TAG_GPIO,"用户加载BLUFI");
                    init_blufi();
                }
                break;
            default:
                break;
            }
            vTaskDelay(150/portTICK_PERIOD_MS);
            
        }
    }
}

void gpio_init_pin(uint32_t gpio_num)
{
    gpio_config_t io_conf;  // 定义一个gpio_config类型的结构体，下面的都算对其进行的配置
    io_conf.intr_type = GPIO_INTR_NEGEDGE;      // 下降沿触发
    io_conf.mode = GPIO_MODE_INPUT;             // 选择输入模式
    io_conf.pin_bit_mask = (1ULL<<gpio_num);  // 配置GPIO_IN寄存器
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_ENABLE;    // 内部上拉

    gpio_config(&io_conf);                      // 最后配置使能


}

void init_gpio(void)
{
    
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));    // 创建一个消息队列，从中获取队列句柄
    gpio_install_isr_service(0);// 注册中断服务

    gpio_init_pin(GPIO_NUM_0);
    gpio_init_pin(GPIO_NUM_2);

    
    gpio_isr_handler_add(GPIO_NUM_0, gpio_isr_handler, (void*) GPIO_NUM_0);// 设置GPIO的中断回调函数
    gpio_isr_handler_add(GPIO_NUM_2, gpio_isr_handler, (void*) GPIO_NUM_2);

    // 创建GPIO检测任务
    xTaskCreate(
            gpio_task,           // 任务函数
            "gpio_task",           // 任务名字
            4096,                  // 任务堆栈大小
            NULL,                  // 传递给任务函数的参数
            10,                    // 任务优先级
            NULL);                // 任務句柄
}

